/*
 * Copyright (c) 2013-2018 上海汇数数据. All rights reserved.
 * @(#) Generics.java 2018-08-05 18:33
 */

package cn.jh.common.core.reflect;

import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * 泛型类型工具。只用于处理 JSON 反序列化时的类型指定。
 *
 * @author Fuchun
 * @since 1.0
 */
@SuppressWarnings("unchecked")
public class Generics {

    public static <E> Class<List<E>> listClass(Class<E> elementClass) {
        TypeToken<List<E>> listTypeToken = new TypeToken<List<E>>() {}
                .where(new TypeParameter<E>() {}, elementClass);
        return (Class<List<E>>) listTypeToken.getRawType();
    }

    public static <E> Class<List<E>> listClass(Type elementType) {
        TypeToken<List<E>> listTypeToken = new TypeToken<List<E>>() {}
                .where(new TypeParameter<E>() {}, (TypeToken<E>) TypeToken.of(elementType));
        return (Class<List<E>>) listTypeToken.getRawType();
    }

    public static <K, V> Class<Map<K, V>> mapClass(Class<K> keyClass, Class<V> valClass) {
        TypeToken<Map<K, V>> typeToken = new TypeToken<Map<K, V>>() {}
                .where(new TypeParameter<K>() {}, keyClass)
                .where(new TypeParameter<V>() {}, valClass);
        return (Class<Map<K, V>>) typeToken.getRawType();
    }

    public static <E> Class<Set<E>> setClass(Class<E> elementClass) {
        TypeToken<Set<E>> typeToken = new TypeToken<Set<E>>() {}
                .where(new TypeParameter<E>() {}, elementClass);
        return (Class<Set<E>>) typeToken.getRawType();
    }

    public static <E> Class<Set<E>> setClass(Type elementType) {
        TypeToken<Set<E>> typeToken = new TypeToken<Set<E>>() {}
            .where(new TypeParameter<E>() {}, (TypeToken<E>) TypeToken.of(elementType));
        return (Class<Set<E>>) typeToken.getRawType();
    }

    private Generics() {
    }
}
